//! # HTTP 客户端工具
//!
//! 提供统一的 HTTP 客户端配置和创建工具，避免在各个模块中重复实现相同的逻辑。

use std::time::Duration;
use serde::{Deserialize, Serialize};

/// 统一的 HTTP 客户端配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HttpClientConfig {
    /// 请求超时时间
    pub timeout: Duration,
    /// 连接超时时间
    pub connect_timeout: Duration,
    /// 读取超时时间
    pub read_timeout: Duration,
    /// 重试次数
    pub retry_count: u32,
    /// 重试延迟
    pub retry_delay: Duration,
    /// 最大连接数
    pub max_connections: usize,
    /// 最大空闲连接数
    pub max_idle_connections: usize,
    /// 连接池空闲超时
    pub pool_idle_timeout: Duration,
    /// 是否启用 Keep-Alive
    pub keep_alive: bool,
    /// User-Agent 字符串
    pub user_agent: String,
    /// 是否启用 HTTP/2
    pub http2_enabled: bool,
    /// 是否启用 GZIP 压缩
    pub gzip_enabled: bool,
}

impl Default for HttpClientConfig {
    fn default() -> Self {
        Self {
            timeout: Duration::from_secs(30),
            connect_timeout: Duration::from_secs(10),
            read_timeout: Duration::from_secs(30),
            retry_count: 3,
            retry_delay: Duration::from_millis(1000),
            max_connections: 100,
            max_idle_connections: 10,
            pool_idle_timeout: Duration::from_secs(90),
            keep_alive: true,
            user_agent: "RustCloud-HttpClient/1.0".to_string(),
            http2_enabled: true,
            gzip_enabled: true,
        }
    }
}

impl HttpClientConfig {
    /// 创建配置构建器
    pub fn builder() -> HttpClientConfigBuilder {
        HttpClientConfigBuilder::new()
    }

    /// 验证配置的有效性
    pub fn validate(&self) -> Result<(), String> {
        if self.timeout.is_zero() {
            return Err("请求超时时间必须大于0".to_string());
        }
        
        if self.connect_timeout.is_zero() {
            return Err("连接超时时间必须大于0".to_string());
        }
        
        if self.read_timeout.is_zero() {
            return Err("读取超时时间必须大于0".to_string());
        }
        
        if self.max_connections == 0 {
            return Err("最大连接数必须大于0".to_string());
        }
        
        if self.max_idle_connections > self.max_connections {
            return Err("最大空闲连接数不能大于最大连接数".to_string());
        }
        
        Ok(())
    }

    /// 为配置服务器场景创建配置
    pub fn for_config_client() -> Self {
        Self {
            timeout: Duration::from_secs(10),
            connect_timeout: Duration::from_secs(5),
            read_timeout: Duration::from_secs(10),
            retry_count: 3,
            retry_delay: Duration::from_millis(500),
            user_agent: "RustCloud-Config-Client/1.0".to_string(),
            ..Default::default()
        }
    }

    /// 为传输层场景创建配置
    pub fn for_transport() -> Self {
        Self {
            timeout: Duration::from_secs(5),
            connect_timeout: Duration::from_secs(3),
            read_timeout: Duration::from_secs(5),
            retry_count: 3,
            retry_delay: Duration::from_millis(1000),
            max_connections: 100,
            user_agent: "RustCloud-Transport/1.0".to_string(),
            ..Default::default()
        }
    }

    /// 为网关场景创建配置
    pub fn for_gateway() -> Self {
        Self {
            timeout: Duration::from_secs(30),
            connect_timeout: Duration::from_secs(5),
            read_timeout: Duration::from_secs(30),
            retry_count: 2,
            retry_delay: Duration::from_millis(500),
            max_connections: 200,
            max_idle_connections: 20,
            user_agent: "RustCloud-Gateway/1.0".to_string(),
            ..Default::default()
        }
    }
}

/// HTTP 客户端配置构建器
pub struct HttpClientConfigBuilder {
    config: HttpClientConfig,
}

impl HttpClientConfigBuilder {
    /// 创建新的构建器
    pub fn new() -> Self {
        Self {
            config: HttpClientConfig::default(),
        }
    }

    /// 设置请求超时时间
    pub fn timeout(mut self, timeout: Duration) -> Self {
        self.config.timeout = timeout;
        self
    }

    /// 设置连接超时时间
    pub fn connect_timeout(mut self, timeout: Duration) -> Self {
        self.config.connect_timeout = timeout;
        self
    }

    /// 设置读取超时时间
    pub fn read_timeout(mut self, timeout: Duration) -> Self {
        self.config.read_timeout = timeout;
        self
    }

    /// 设置重试次数
    pub fn retry_count(mut self, count: u32) -> Self {
        self.config.retry_count = count;
        self
    }

    /// 设置重试延迟
    pub fn retry_delay(mut self, delay: Duration) -> Self {
        self.config.retry_delay = delay;
        self
    }

    /// 设置最大连接数
    pub fn max_connections(mut self, count: usize) -> Self {
        self.config.max_connections = count;
        self
    }

    /// 设置最大空闲连接数
    pub fn max_idle_connections(mut self, count: usize) -> Self {
        self.config.max_idle_connections = count;
        self
    }

    /// 设置连接池空闲超时
    pub fn pool_idle_timeout(mut self, timeout: Duration) -> Self {
        self.config.pool_idle_timeout = timeout;
        self
    }

    /// 设置是否启用 Keep-Alive
    pub fn keep_alive(mut self, enabled: bool) -> Self {
        self.config.keep_alive = enabled;
        self
    }

    /// 设置 User-Agent
    pub fn user_agent(mut self, user_agent: String) -> Self {
        self.config.user_agent = user_agent;
        self
    }

    /// 设置是否启用 HTTP/2
    pub fn http2_enabled(mut self, enabled: bool) -> Self {
        self.config.http2_enabled = enabled;
        self
    }

    /// 设置是否启用 GZIP 压缩
    pub fn gzip_enabled(mut self, enabled: bool) -> Self {
        self.config.gzip_enabled = enabled;
        self
    }

    /// 构建配置
    pub fn build(self) -> Result<HttpClientConfig, String> {
        self.config.validate()?;
        Ok(self.config)
    }
}

impl Default for HttpClientConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// HTTP 客户端工厂
pub struct HttpClientFactory;

impl HttpClientFactory {
    /// 为 reqwest 客户端创建构建器
    #[cfg(feature = "reqwest")]
    pub fn create_reqwest_builder(config: &HttpClientConfig) -> reqwest::ClientBuilder {
        let mut builder = reqwest::Client::builder()
            .timeout(config.timeout)
            .connect_timeout(config.connect_timeout)
            .pool_max_idle_per_host(config.max_idle_connections)
            .pool_idle_timeout(config.pool_idle_timeout)
            .user_agent(&config.user_agent);

        if config.keep_alive {
            builder = builder.tcp_keepalive(Some(Duration::from_secs(60)));
        }

        if config.http2_enabled {
            builder = builder.http2_prior_knowledge();
        }

        builder
    }

    /// 创建 reqwest 客户端
    #[cfg(feature = "reqwest")]
    pub fn create_reqwest_client(config: &HttpClientConfig) -> Result<reqwest::Client, reqwest::Error> {
        Self::create_reqwest_builder(config).build()
    }

    /// 创建默认的 reqwest 客户端
    #[cfg(feature = "reqwest")]
    pub fn create_default_reqwest() -> Result<reqwest::Client, reqwest::Error> {
        let config = HttpClientConfig::default();
        Self::create_reqwest_client(&config)
    }

    /// 为配置客户端创建 reqwest 客户端
    #[cfg(feature = "reqwest")]
    pub fn create_config_client() -> Result<reqwest::Client, reqwest::Error> {
        let config = HttpClientConfig::for_config_client();
        Self::create_reqwest_client(&config)
    }

    /// 为传输层创建 reqwest 客户端
    #[cfg(feature = "reqwest")]
    pub fn create_transport_client() -> Result<reqwest::Client, reqwest::Error> {
        let config = HttpClientConfig::for_transport();
        Self::create_reqwest_client(&config)
    }

    /// 为网关创建 reqwest 客户端
    #[cfg(feature = "reqwest")]
    pub fn create_gateway_client() -> Result<reqwest::Client, reqwest::Error> {
        let config = HttpClientConfig::for_gateway();
        Self::create_reqwest_client(&config)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_http_client_config_default() {
        let config = HttpClientConfig::default();
        assert!(config.validate().is_ok());
        assert_eq!(config.timeout, Duration::from_secs(30));
        assert_eq!(config.retry_count, 3);
        assert_eq!(config.max_connections, 100);
        assert!(config.keep_alive);
    }

    #[test]
    fn test_http_client_config_builder() {
        let config = HttpClientConfig::builder()
            .timeout(Duration::from_secs(15))
            .retry_count(5)
            .max_connections(200)
            .user_agent("Test-Client/1.0".to_string())
            .build()
            .unwrap();

        assert_eq!(config.timeout, Duration::from_secs(15));
        assert_eq!(config.retry_count, 5);
        assert_eq!(config.max_connections, 200);
        assert_eq!(config.user_agent, "Test-Client/1.0");
    }

    #[test]
    fn test_specialized_configs() {
        let config_client = HttpClientConfig::for_config_client();
        assert_eq!(config_client.timeout, Duration::from_secs(10));
        assert_eq!(config_client.user_agent, "RustCloud-Config-Client/1.0");

        let transport = HttpClientConfig::for_transport();
        assert_eq!(transport.timeout, Duration::from_secs(5));
        assert_eq!(transport.user_agent, "RustCloud-Transport/1.0");

        let gateway = HttpClientConfig::for_gateway();
        assert_eq!(gateway.timeout, Duration::from_secs(30));
        assert_eq!(gateway.max_connections, 200);
        assert_eq!(gateway.user_agent, "RustCloud-Gateway/1.0");
    }

    #[test]
    fn test_config_validation() {
        let mut config = HttpClientConfig::default();
        
        // 正常配置应该通过验证
        assert!(config.validate().is_ok());
        
        // 无效配置应该失败
        config.timeout = Duration::from_secs(0);
        assert!(config.validate().is_err());
        
        config.timeout = Duration::from_secs(30);
        config.max_connections = 0;
        assert!(config.validate().is_err());
        
        config.max_connections = 100;
        config.max_idle_connections = 200;
        assert!(config.validate().is_err());
    }
}